package com.kool.kreport.common.util;

import com.kool.kreport.common.constant.ErrorCode;
import com.kool.kreport.common.exception.AppException;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

/**
 * 大文件处理工具类
 * 建议1G以上的文件才用这个工具类
 *
 * @author luyu
 */
@Slf4j
public class BigFileUtil {

    /**
     * 复制文件
     *
     * @param fromPath
     * @param toPath
     */
    public static void copy(String fromPath, String toPath) {
        RandomAccessFile fromFile = null;
        RandomAccessFile toFile = null;
        try {
            fromFile = new RandomAccessFile(fromPath, "r");
            toFile = new RandomAccessFile(toPath, "rw");
            FileChannel channel = fromFile.getChannel();
            FileChannel channel2 = toFile.getChannel();

            int bufferSize = 100 * 1024 * 1024;
            if (bufferSize > channel.size()) {
                bufferSize = (int) channel.size();
            }
            ByteBuffer buff = ByteBuffer.allocate(bufferSize);

            long pos = 0;
            while (channel.read(buff) > 0) {
                buff.flip();
                channel2.write(buff, pos);
                pos += buff.limit();
                buff.clear();
            }

        } catch (IOException e) {
            log.error(e.getMessage(), e);
            throw new AppException(ErrorCode.BUSINESS_ERROR, "复制大文件错误，错误信息：" + e.getMessage());
        } finally {
            closeIO(fromFile);
            closeIO(toFile);
        }
    }

    /**
     * 关闭io连接
     *
     * @param io
     */
    private static void closeIO(RandomAccessFile io) {
        if (io != null) {
            try {
                io.close();
            } catch (IOException e) {
                log.error(e.getMessage(), e);
                throw new AppException(ErrorCode.BUSINESS_ERROR, "IO错误，错误信息：" + e.getMessage());
            }
        }

    }

    /**
     * 零拷贝
     *
     * @param fromPath
     * @param toPath
     * @throws IOException
     */
    public static void copyDirect(String fromPath, String toPath) throws IOException {
        RandomAccessFile fromFile = null;
        RandomAccessFile toFile = null;
        try {
            fromFile = new RandomAccessFile(fromPath, "r");
            toFile = new RandomAccessFile(toPath, "rw");
            FileChannel channelFrom = fromFile.getChannel();
            FileChannel channelTo = toFile.getChannel();

            channelFrom.transferTo(0, channelFrom.size(), channelTo);
        } catch (IOException e) {
            throw e;
        } finally {
            closeIO(fromFile);
            closeIO(toFile);
        }
    }

}
